package com.pig4cloud.pigx.gateway;

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.HexUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.util.CharsetUtil;
import io.netty.util.internal.logging.InternalLogger;
import io.netty.util.internal.logging.InternalLoggerFactory;
import lombok.extern.slf4j.Slf4j;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;

@Slf4j
public class CustomDecoder extends ByteToMessageDecoder {

    private static final InternalLogger logger = InternalLoggerFactory.getInstance(CustomDecoder.class);
    private final byte DELIMITER = 0x7E;

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        // 查找分隔符的位置
        int delimiterIndex = in.bytesBefore(DELIMITER);

        // 如果找到了分隔符
        if (delimiterIndex != -1) {
            // 跳过分隔符之前的数据
            in.skipBytes(delimiterIndex);

            // 读取分隔符之后的数据
            int readableBytes = in.readableBytes();
            byte[] data = new byte[readableBytes];
            in.readBytes(data);
            log.info("打印内容:{}",data.length);

            // 添加解码后的消息到输出列表
            out.add(data);

            // 打印字节数组的十六进制表示
            logger.info("Received message with delimiter: {}", new String(data));
        } else {
            // 如果没有找到分隔符，则清空缓冲区
            in.clear();
        }
    }

    public static void main(String[] args) {
        String hexString = "7e0022900008000010241902ff0001aa1f97010813ffff23122416564801ff0052b8ee4139ff";
        byte[] data = hexStringToByteArray(hexString);

        log.info("报文数组:{}",data);

        log.info("报文长度:{}",data.length);

        log.info("设备报文:{}", HexUtil.encodeHexStr(data));

        //处理粘包
        for (int i = 0; i < data.length; i++) {
            byte datum = data[i];
            if (datum != 0x7E) continue;
            if (i == 0) break;
            byte[] temp = new byte[data.length - i];
            System.arraycopy(data, i, temp, 0, data.length - i);
            data = temp;
            break;
        }


        byte frameHeader = data[0];
        if (frameHeader != 0x7E) {
            log.error("报文不合法,帧头:{}", HexUtil.toHex(frameHeader));
        }
        //从帧类型开始，到数据段结束的所有字节数
        byte[] dataLength = new byte[2];
        System.arraycopy(data, 1, dataLength, 0, 2);
        int length = ((dataLength[dataLength[0]]) << 8) | (byte2Hex(dataLength[1]));
		log.info("长度：{}    {}", length, HexUtil.toHex(length));
        //帧类型到数据段的长度
        int frameType2DataSegment = length - 12;
		log.info("帧类型到数据段的长度：{}    {}", dataLength, HexUtil.toHex(frameType2DataSegment));
        byte[] macAddress = new byte[8];
        System.arraycopy(data, 4, macAddress, 0, 8);
        String macStr = HexUtil.encodeHexStr(macAddress);
        log.info("安帕尔私有协议设备MAC:{}", macStr);
        byte[] dataSegment = new byte[length - 12];
        System.arraycopy(data, 15, dataSegment, 0, frameType2DataSegment);
        log.info("数据内容:{}", HexUtil.encodeHexStr(dataSegment));


        //读取的索引
        Integer readIndex;
        byte dateFrameHeader = dataSegment[0];
        if (byte2Hex(dateFrameHeader) != 0xAA) {
            log.error("数据段帧头错误:{}", HexUtil.toHex(byte2Hex(dateFrameHeader)));
        }

        byte deviceProperties = dataSegment[4];
        log.info("设备属性:{}", HexUtil.toHex(byte2Hex(deviceProperties)));
        byte protocolVersion = dataSegment[5];
        log.info("协议版本:{}", HexUtil.toHex(byte2Hex(protocolVersion)));
        byte[] alarmInfo = new byte[2];
        System.arraycopy(dataSegment, 6, alarmInfo, 0, alarmInfo.length);
        ArrayUtil.swap(alarmInfo, 0, 1);

        // 该项置位为发生报警，置零为该项未报警。多种报警信息并存支持，2 字节。部分功能为预留功能。
        // 常见的有：00 00 正常；01 00 低报警；02 00 高报警；04 00 超量程
        int value = ((alarmInfo[0] & 0xFF) << 8) | (alarmInfo[1] & 0xFF);
        log.info("报警信息:{}", String.format("0x%04X", value));
        byte[] timeStamp = new byte[6];
        System.arraycopy(dataSegment, 8, timeStamp, 0, timeStamp.length);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyMMddHHmmss");
        LocalDateTime receptionTime = LocalDateTime.parse(HexUtil.encodeHexStr(timeStamp), formatter);
        log.info("时间戳:{},{}", HexUtil.encodeHexStr(timeStamp), receptionTime);
        byte numberData = dataSegment[14];
        log.info("数据个数:{}", HexUtil.toHex(byte2Hex(numberData)));
        readIndex = 15;
        for (int i = 0; i < numberData; i++) {
            byte[] gasTypeIdAndUnit = new byte[2];
            readIndex = copyAndMoveReadIndexOrder(dataSegment, readIndex, gasTypeIdAndUnit);
            log.info("气体类型和单位:0x{}", HexUtil.encodeHexStr(gasTypeIdAndUnit));
            byte[] val = new byte[4];
            readIndex = copyAndMoveReadIndex(dataSegment, readIndex, val);
            String vatStr = HexUtil.encodeHexStr(val);
            log.info("气体值数组:{}",val);
            float gasValFloat = ByteBuffer.wrap(val).order(ByteOrder.LITTLE_ENDIAN).getFloat() ;
            DecimalFormat df = new DecimalFormat("#.###");
            String gasVal = df.format(gasValFloat);
            gasTypeIdAndUnit = ArrayUtil.swap(gasTypeIdAndUnit, 0, 1);
            value = ((gasTypeIdAndUnit[0] & 0xFF) << 8) | (gasTypeIdAndUnit[1] & 0xFF);
            int typeId = value & 0xFFF;
            int unitId = (value >> 12) & 0xF;
            String gasType = String.format("0x%04X", typeId);
            String gasUnit = String.format("0x%02X", unitId);

            log.info("气体类型:{}",gasType);
            log.info("单位:{},",gasUnit);
            log.info("值:0x{},{}", vatStr, gasVal);
        }


    }

    /**
     * 正常复制
     */
    public static Integer copyAndMoveReadIndex(byte[] src, Integer readIndex, byte[] target) {
        System.arraycopy(src, readIndex, target, 0, target.length);
        return readIndex + target.length;
    }

    /**
     * 大小端转换
     */
    public static Integer copyAndMoveReadIndexOrder(byte[] src, Integer readIndex, byte[] target) {
        System.arraycopy(src, readIndex, target, 0, target.length);
        target = ByteBuffer.wrap(target).order(ByteOrder.LITTLE_ENDIAN).array();
        return readIndex + target.length;
    }

    public static int calculateLength(byte[] bytes) {
        if (bytes.length != 2) {
            throw new IllegalArgumentException("The input byte array must contain exactly two bytes.");
        }

        // 将字节数组中的两个字节转换为十进制数值，并组合起来计算长度
        int length = (bytes[0] & 0xFF) << 8 | (bytes[1] & 0xFF);
        return length;
    }

    public static int byte2Hex(byte b) {
        return b & 0XFF;
    }

    public static byte[] hexStringToByteArray(String hexString) {
        int length = hexString.length();
        byte[] byteArray = new byte[length / 2];
        for (int i = 0; i < length; i += 2) {
            byteArray[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
                    + Character.digit(hexString.charAt(i + 1), 16));
        }
        return byteArray;
    }

}